package com.qqt.csr.common.idempotent;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.util.ReflectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * @author:
 * @date: 2024-07-04 14:50
 */
public class RequestKeyGenerator {
    
    /**
     * 获取LockKey
     *
     * @param joinPoint 切入点
     * @return
     */
    public static String getLockKey(ProceedingJoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Idempotent idempotent = method.getAnnotation(Idempotent.class);
        final Object[] args = joinPoint.getArgs();
        final Parameter[] parameters = method.getParameters();
        StringBuilder lockKey = new StringBuilder();
        for (int i = 0; i < parameters.length; i++) {
            //遍历方法上，定义的参数
            final RequestKeyParam keyParam = parameters[i].getAnnotation(RequestKeyParam.class);
            if (keyParam == null) {
                continue;
            }
            lockKey.append(idempotent.delimiter()).append(args[i]);
        }

        if (StringUtils.isEmpty(lockKey.toString())) {
            //遍历方法参数的属性值
            final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
            for (int i = 0; i < parameterAnnotations.length; i++) {
                final Object object = args[i];
                ReflectionUtils.doWithFields(object.getClass(), field -> {
                    final RequestKeyParam annotation = field.getAnnotation(RequestKeyParam.class);
                    if (annotation == null) {
                        return;
                    }
                    field.setAccessible(true);
                    lockKey.append(idempotent.delimiter()).append(ReflectionUtils.getField(field, object));
                });

            }
        }

        if (lockKey.isEmpty()) {
            return null;
        }

        return idempotent.keyPrefix() + idempotent.model() + lockKey;
    }
}
